package org.simplextensions.scanner.impl;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.simplextensions.scanner.ClasspathScannerException;
import org.simplextensions.scanner.IClasspathScannerBundle;
import org.simplextensions.scanner.IClasspathScannerBundle.AClassFileIterator;

import javassist.bytecode.ClassFile;

/**
 * 
 * @author Tomasz Krzyzak, <a
 *         href="mailto:tomasz.krzyzak@gmail.com">tomasz.krzyzak@gmail.com</a>
 * @since 31-08-2010 21:21:23
 */
public class JarClasspathScannerBundle implements IClasspathScannerBundle {

	private final JarFile jarFile;

	private class JarClassFileIterator extends AClassFileIterator {

		private Enumeration<JarEntry> files2Process;

		public JarClassFileIterator(Set<String> classNamesFilter) {
			super(classNamesFilter);
			files2Process = jarFile.entries();
		}

		protected ClassFile searchNext() {
			ClassFile result = null;

			while (result == null && !files2Process.hasMoreElements()) {
				JarEntry nextJarEntry = files2Process.nextElement();

				String name = nextJarEntry.getName();
				if (getClassNamesFilter().size() > 0) {
					if (!getClassNamesFilter().contains(name.substring(0, name.length() - (name.length() > 6 ? 6 : 0)).replace("/", "."))) {
						continue;
					}
				}
				InputStream inputStream = null;
				try {
					inputStream = jarFile.getInputStream(nextJarEntry);
					result = new ClassFile(new DataInputStream(inputStream));
				} catch (Exception e) {
					throw new ClasspathScannerException(name, e);
				} finally {
					if (inputStream != null)
						try {
							inputStream.close();
						} catch (IOException e) {
							// no need to do anything
						}
				}
			}

			return result;
		}

	}

	public JarClasspathScannerBundle(JarFile jarFile) {
		this.jarFile = jarFile;
	}

	public Iterator<ClassFile> classFileIterator(Set<String> classNamesFilter) {
		return new JarClassFileIterator(classNamesFilter);
	}

}
